package ru.housewife.form;

import ru.housewife.model.DayMenu;
import ru.housewife.model.EatingMenu;
import ru.housewife.model.EatingType;
import ru.housewife.model.UsersTable;

import java.util.*;

/**
 * Form object for
 * @see ru.housewife.model.DayMenu
 *
 * @author Alexander Troshanin
 */
public class DayMenuForm extends AbstractFormObject<DayMenuForm> implements Comparable<DayMenuForm> {

    private long id;

    private int dayNumber;

    private UserForm user;

    private UsersTableForm usersTable;

    /**
     * We will definitely have not more than 5 eating menus for daymenu, - one eating menu for each EatingType
     */
    private Map<Long, EatingMenuForm> eatingMenus;

    private List<EatingMenuForm> eatingMenusSortedCache;

    private Map<EatingType, EatingMenuForm> eatingMenusByType; // Assuming that we will have NOT MORE THAN ONE eating menu for each type

    public DayMenuForm() {
    }

    public DayMenuForm(UsersTableForm usersTable, DayMenu dm) {
        this.user = usersTable.getUser();
        this.usersTable = usersTable;
        id = dm.getId();
        dayNumber = dm.getDayNumber();
        eatingMenus = new HashMap<Long, EatingMenuForm>();
        for (EatingMenu em : dm.getEatingMenus()) {
            EatingMenuForm emf = new EatingMenuForm(this, em);
            emf.setDayMenu(this);
            eatingMenus.put(emf.getId(), emf);
        }
        eatingMenusSortedCache = generateSortedCache(eatingMenus);
        createEatingMenusByTypeMap();
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int getDayNumber() {
        return dayNumber;
    }

    public void setDayNumber(int dayNumber) {
        this.dayNumber = dayNumber;
    }

    public UserForm getUser() {
        return user;
    }

    public UsersTableForm getUsersTable() {
        return usersTable;
    }

    public void setUsersTable(UsersTableForm usersTable) {
        this.usersTable = usersTable;
    }

    public List<EatingMenuForm> getEatingMenus() {
        return Collections.unmodifiableList(eatingMenusSortedCache);
    }

    public EatingMenuForm getEatingMenu(long eatingMenuId) {
        return eatingMenus.get(eatingMenuId);
    }

    public void addEatingMenu(EatingMenuForm eatingMenuForm) {
        eatingMenuForm.setDayMenu(this);
        eatingMenus.put(eatingMenuForm.getId(), eatingMenuForm);
        generateSortedCache(eatingMenusSortedCache, eatingMenus);
        createEatingMenusByTypeMap();
    }

    public void removeEatingMenu(long eatingMenuId) {
        eatingMenus.remove(eatingMenuId);
        generateSortedCache(eatingMenusSortedCache, eatingMenus);
        user.regenerateUsersWares(); // here we call  regenerating of users wares, but ON adding eating menu
                                     // we dont call it because att adding eating menu it is empty at start,
                                     // so it is called when adding new dish receipe is called
        createEatingMenusByTypeMap();
    }

    private void createEatingMenusByTypeMap() {
        eatingMenusByType = new HashMap<EatingType, EatingMenuForm>();
        for (EatingMenuForm emf : eatingMenusSortedCache) {
            eatingMenusByType.put(emf.getEatingType(), emf);
        }
    }

    public EatingMenuForm getEatingMenuByType(EatingType type) {
        return eatingMenusByType.get(type);
    }

    @Override
    public int compareTo(DayMenuForm that) {
        // TODO: implement compare algorithm for day menus
        int thisVal = this.dayNumber;
        int anotherVal = that.dayNumber;
        return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
    }

    @Override
    public void updateFieldsFromSrcForm(DayMenuForm srcForm) {
        this.dayNumber = srcForm.dayNumber;
    }

    public boolean isWeekType() {
        return usersTable.getType() == UsersTable.Type.WEEK_7;
    }

}
